// $Id: drawTHnSparse.C 52501 2011-11-02 10:26:47Z richterm $
/*
 * Drawing macro for reading the THnSparse output of the 
 * HLT/QA/tasks/AliAnalysisTaskHLTCentralBarrel.cxx task.
 * 
 * The cuts are user defined around lines 124-128 as members
 * of an array of structures. Now there are a few predefined sets of cuts.
 * 
 * The input file contains information about the run number
 * and date that will appear in the canvas title.
 * 
 * The cuts are turned into strings and incorporated in the
 * name of the output file, which contains canvases with event
 * and track properties for HLT and offline.
 *  
 * Since the run information is available, there will be a new
 * folder created and the canvas ROOT files will be saved in there.
 *
 * The macro should be compiled before running:
 *
 * root[0] .L drawTHnSparse.C++
 * root[1] drawTHnSparse("HLT-OFFLINE-CentralBarrel-comparison.root")
 *
 * In case more than 1 sets of cuts have been used, the macro creates a canvas
 * and overlays the different histograms both for HLT and OFF, if the latter
 * is available.
 * 
 * If the user wants more flexibility adding the TLegend that explains the cuts,
 * the macro HLT/QA/tasks/macros/overlayPlots.C should be used. For the current one
 * the legends of the histograms are somewhat difficult to print at the moment.
 * The text keeps appearing in the wrong location (Kelly, 17.05.2011).
 *
 * @ingroup alihlt_qa
 * @author Kalliopi.Kanaki@ift.uib.no 
 */

#if !defined(__CINT__) || defined(__MAKECINT__)
#include "TSystem.h"
#include "TROOT.h"
#include "TFile.h"
#include "TString.h"
#include "TList.h"
#include "THnSparse.h"
#include "TCanvas.h"
#include "TText.h"
#include "TPaveText.h"
#include "TPaveStats.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TH3D.h"
#include "TLegend.h"
#include "TStyle.h"
#include "TPad.h"
#include <iostream>
#include <iomanip>
#include <cstdlib>
using std::endl;
#endif

//---------- forward declerations ---------------//

struct cuts { float minEta; float maxEta; float minPt; float maxPt; float minDCAr; float maxDCAr; float minDCAz; float maxDCAz;
	      int minTPCclus; int maxTPCclus; int minITSclus; int maxITSclus; int vertexStatus; float vertexZ; int minV0cent; int maxV0cent;	 
            };
vector<TString> outputNames;
void cutStudies( TString folder,  THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText, cuts cut);
void printStats(TH1D *hlt, TH1D *off);
void defineYaxisMax(TH1D *h1, TH1D *h2);
void printLegend(TH1D *hlt, TH1D *off);
void plot2D( THnSparse* h, TText *hText, TString folder, cuts cut );
void plotEventQuantities(THnSparse* heventHLT, THnSparse* heventOFF, TText* hText, TString folder,TString fBeamType);
TString fix1DTitle(const char* c);
TString fix2DTitle(const char* c1, const char* c2);
TString cutsToString( cuts cut );
void plotTrackQuantities( THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText, TString folder, cuts cut);
void printCuts(cuts cut);	

//------------------------------------------------------------------//		

void drawTHnSparse(TString beamType="p-p", TString inputFile="HLT-OFFLINE-CentralBarrel-comparison.root"){
 
  gROOT->SetStyle("Plain");
  gStyle->SetPalette(1);
  gStyle->SetOptStat("emr");
  gStyle->SetTitleX(gStyle->GetPadLeftMargin());
  TH1::AddDirectory(kFALSE);

  TFile *file = TFile::Open(inputFile);
  if(!file){
    printf("Error: No file %s in folder.\n", inputFile.Data());
    return;
  }
  TList *list = static_cast<TList*>(file->Get("esd_thnsparse"));
  if(!list){
    printf("Error: No List contained in file %s.\n", inputFile.Data());
    return;
  }
  THnSparseF *heventHLT = (THnSparseF*)list->FindObject("fEventHLT"); 
  if(!heventHLT){
      printf("Error: There is no HLT THnSparse object in file %s\n", inputFile.Data());
      return;
  }
  THnSparseF *heventOFF = (THnSparseF*)list->FindObject("fEventOFF");  
  if(!heventOFF){
      printf("Error: There is no OFF THnSparse object in file %s\n", inputFile.Data());
      return;
  } 
  THnSparseF *htrackHLT = (THnSparseF*)list->FindObject("fTrackHLT");
  if(!htrackHLT){
      printf("Error: No HLT THnSparse object found\n");
      return;
  } 
  THnSparseF *htrackOFF = (THnSparseF*)list->FindObject("fTrackOFF");  
  if(!htrackOFF){
      printf("Error: No OFF THnSparse object found\n");
      return;
  }
      
  TText *hText = (TText*)list->FindObject("text");
  if(!hText) printf("No hText\n");

  TString folder = "CentralBarrelTask_";
  folder += hText->GetTitle();
  folder.ReplaceAll(" ",""); 
  folder.ReplaceAll(",","_");    
  gSystem->Exec("mkdir "+folder); // create a folder whose name contains run number and date of run
  
  if(heventHLT->GetEntries()>0 || heventOFF->GetEntries()>0) plotEventQuantities(heventHLT,heventOFF,hText,folder,beamType);
  else {
    if(heventHLT->GetEntries()==0) printf("\nThe HLT event THnSparse contains 0 entries\n");
    if(heventOFF->GetEntries()==0) printf("\nThe OFF event THnSparse contains 0 entries\n");
  }   
   
  cuts p[] = {                                                                                                                                                                               
         // eta    pt      DCAr     DCAz    TPCclus  ITSclus  vtxStatus  |vtxZ|   V0cent                                                                                                
       {-1, 1,  0,   10, -10, 10, -10, 10,  0, 200,   0, 10,      2,       10,   0, 100},                                                                                                    
       {-1, 1,  0.30,10,  -7,  7,  -7,  7,  0, 200,   0, 10,      2,       10,   0, 100},                                                                                                    
       {-1, 1,  0.60,10,  -7,  7,  -7,  7,  0, 200,   0, 10,      2,       10,   0, 100},                                                                                                    
       {-1, 1,  0.90,10,  -7,  7,  -7,  7,  0, 200,   0, 10,      2,       10,   0, 100}                                                                                                     
  };                                                                                                                                                                                         
  const int nCutSets = sizeof(p)/sizeof(cuts);
 
  for(int i=0; i<nCutSets; ++i) cutStudies(folder, htrackHLT, htrackOFF, hText, p[i]); 
  
  // the TString vector outputNames is filled at the end of the cutStudies() call with the name of the output name for every cut.  
  // If there is more than 1 set of cuts, then there will be 2 new canvases created, HLT and OFF respectively with the overlaid track properties
     
  if(outputNames.size()>=2){          
     TString tmp = "overlaid HLT track distributions for ";
     tmp += hText->GetTitle();
     TCanvas *ovHLT = new TCanvas("ovHLT",tmp,1200,800);
     ovHLT->Divide(4,2);
     
     tmp = "overlaid OFF track distributions for ";
     tmp += hText->GetTitle();
     TCanvas *ovOFF = new TCanvas("ovOFF",tmp,1200,800);
     ovOFF->Divide(4,2);

     TCanvas *ca; TFile *ff; TPad *pad; 
     TH1D *hlt[outputNames.size()];
     TH1D *off[outputNames.size()];
          
     for(int j=1; j<9; j++){ // loop over the pads of the canvas "ov" with dimension 3x3     
       for(UInt_t i=0; i<outputNames.size(); i++){ // loop over the files with different sets of cuts
    	      
     	   ff = TFile::Open(outputNames[i].Data());   
     	   if(!ff || ff->IsZombie()){
     	      printf("Non-existent, corrupted or zombie file %s\n", outputNames[i].Data());
     	      continue;
     	   } 
     	   ca  = (TCanvas*)ff->GetObjectUnchecked("can3");	       
     	   if(!ca){
     	      printf("Empty canvas in file %s\n", outputNames[i].Data());
     	      continue;
     	   }	   
     	   pad = (TPad*)ca->GetListOfPrimitives()->FindObject(Form("can3_%d",j));	   
     	   if(!pad){
     	      printf("Empty pad in canvas %s\n", ca->GetName());
     	      continue; 	
     	   }

     	   hlt[i] =(TH1D*)pad->FindObject(Form("fTrackHLT_proj_%d",j-1)); 	   	   	   
     	   if(!hlt[i]){
     	      printf("Empty HLT histogram for cuts i=%d, file %s\n", i, outputNames[i].Data());
     	      continue;
     	   }
	   
	   ovHLT->cd(j); 	       	  
   	   if(i==0){
	      hlt[i]->Draw();
	   }
     	   else { 
     	     hlt[i]->SetLineColor(i+1); 
     	     defineYaxisMax(hlt[0], hlt[i]); 
     	     hlt[i]->Draw("sames");
     	   }
     	   if(i>0) printStats(hlt[i-1], hlt[i]);
	   
  	   off[i] =(TH1D*)pad->FindObject(Form("fTrackOFF_proj_%d",j-1));
	   if(!off[i]){
     	      printf("Empty OFF histogram for cuts i=%d, file %s\n", i, outputNames[i].Data());
     	      continue;
     	   }
	   
	   ovOFF->cd(j);	   
     	   if(i==0){
	      off[i]->SetLineColor(kBlack); 
	      off[i]->Draw();
              TPaveStats *st = (TPaveStats*)off[i]->FindObject("stats"); 
              st->SetTextColor(kBlack);
	      ovOFF->Update();
	   }
     	   else { 
     	     off[i]->SetLineColor(i+1); 
     	     defineYaxisMax(off[0], off[i]); 
     	     off[i]->Draw("sames");
     	   }
	   if(i>0) printStats(off[i-1], off[i]);
	   
     	   ff->Close(); 				    
       } // end of loop over files 
     } // end of loop over canvas pads
     file->Close();  
     ovHLT->Update(); 
     ovHLT->SaveAs(folder+"/overlaid_HLT_track_cuts.root");
     ovHLT->Print(folder+"/overlaid_HLT_track_cuts.png");  
     ovOFF->Update();
     ovOFF->SaveAs(folder+"/overlaid_OFF_track_cuts.root");
     ovOFF->Print(folder+"/overlaid_OFF_track_cuts.png");  
     //delete ovHLT;
     //delete ovOFF;
  } // end if for counter>=2
  return;
}

// ============== main function for filling the track properties, 1D and 2D ================ //

void cutStudies( TString folder, THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText, cuts cut){
 
  printCuts(cut);
  plotTrackQuantities(htrackHLT, htrackOFF, hText, folder, cut); 
  if(htrackHLT->GetEntries()>0) plot2D(htrackHLT, hText, folder, cut);  
  if(htrackOFF->GetEntries()>0) plot2D(htrackOFF, hText, folder, cut);
   
  TString strcuts = cutsToString(cut);  
  outputNames.push_back(folder+"/track_properties_"+strcuts+".root");
  return;
}

void plotEventQuantities(THnSparse* heventHLT, THnSparse* heventOFF, TText* hText, TString folder, TString fBeamType){

  TString tmp = "vertex event properties for ";
  tmp += hText->GetTitle();
  TCanvas *can1 = new TCanvas("can1",tmp,1200,700);
  can1->Divide(3,2); 
  
  heventHLT->GetAxis(8)->SetRangeUser(1,1); // select events with existing primary vertex	
  heventOFF->GetAxis(8)->SetRangeUser(1,1);
  TH1D *hlt = NULL; 
  TH1D *off = NULL; 
  
  for(int i=0; i<6; i++){ // loop for HLT/OFF primary and SPD vertex xyz
      can1->cd(i+1);
      hlt = heventHLT->Projection(i); if(!hlt){ printf("plotEventQuantities: empty HLT histogram, projection %d\n",i); continue; }
      off = heventOFF->Projection(i); if(!off){ printf("plotEventQuantities: empty OFF histogram, projection %d\n",i); continue; }
      off->SetLineColor(2); 
      hlt->SetTitle(fix1DTitle(heventHLT->Projection(i)->GetTitle())); 
      off->SetTitle(fix1DTitle(heventOFF->Projection(i)->GetTitle()));       
      TString s = hlt->GetTitle();	
      if(s.Contains("primary")){ 
  	 s+=" (cm)";
  	 hlt->SetXTitle(s); 
  	 off->SetXTitle(s);    
      }
      if(off->GetEntries()>0) defineYaxisMax(hlt, off);
      
      if(hlt->GetEntries()>0) hlt->Draw();
      if(off->GetEntries()>0) off->Draw("sames");
      if(hlt->GetEntries()>0 && off->GetEntries()>0) printStats(hlt, off);
      if(off->GetEntries()>0 && i==0 ) printLegend(hlt,off);
  }
  
  tmp = "general event properties for ";
  tmp += hText->GetTitle(); 
  TCanvas *can2 = new TCanvas("can2",tmp,1200,700);
  can2->Divide(3,2);
  
  can2->cd(1); // track multiplicity
  if(fBeamType.Contains("p-p")){
    heventHLT->GetAxis(7)->SetRangeUser(0,1000);
    heventOFF->GetAxis(7)->SetRangeUser(0,1000);
  }
  hlt = heventHLT->Projection(7); 
  off = heventOFF->Projection(7); 
  off->SetLineColor(2); 
  hlt->SetTitle(fix1DTitle(heventHLT->Projection(7)->GetTitle())); 
  off->SetTitle(fix1DTitle(heventOFF->Projection(7)->GetTitle()));	 
  if(off->GetEntries()>0) defineYaxisMax(hlt, off);
  if(hlt->GetEntries()>0) hlt->Draw();
  if(off->GetEntries()>0){ off->Draw("sames"); printLegend(hlt,off); }
  if(hlt->GetEntries()>0 && off->GetEntries()>0) printStats(hlt, off);

  can2->cd(2); // number of contributors
  if(fBeamType.Contains("p-p")){
    heventHLT->GetAxis(6)->SetRangeUser(0,1000);
    heventOFF->GetAxis(6)->SetRangeUser(0,1000);
  }
  hlt = heventHLT->Projection(6); 
  off = heventOFF->Projection(6); 
  off->SetLineColor(2); 
  hlt->SetTitle(fix1DTitle(heventHLT->Projection(6)->GetTitle())); 
  off->SetTitle(fix1DTitle(heventOFF->Projection(6)->GetTitle()));	 
  if(off->GetEntries()>0) defineYaxisMax(hlt, off);
  if(hlt->GetEntries()>0) hlt->Draw();
  if(off->GetEntries()>0) off->Draw("sames");
  if(hlt->GetEntries()>0 && off->GetEntries()>0) printStats(hlt, off);
   
  can2->cd(3); // vertex status
  hlt = heventHLT->Projection(8); 
  off = heventOFF->Projection(8); 
  off->SetLineColor(2); 
  hlt->SetTitle(fix1DTitle(heventHLT->Projection(8)->GetTitle())); 
  off->SetTitle(fix1DTitle(heventOFF->Projection(8)->GetTitle()));	 
  if(off->GetEntries()>0) defineYaxisMax(hlt, off);
  if(hlt->GetEntries()>0) hlt->Draw();
  if(off->GetEntries()>0) off->Draw("sames");
  if(hlt->GetEntries()>0 && off->GetEntries()>0) printStats(hlt, off); 
  
  can2->cd(4); // # of contributors vs. track multiplicity for HLT
  TH2D *h = heventHLT->Projection(6,7);
  TString s1 = fix2DTitle(heventHLT->Projection(6)->GetTitle(), heventHLT->Projection(7)->GetTitle()); s1+=" (HLT)";
  h->SetTitle(s1);
  h->Draw("colz");
  
  can2->cd(5); // # of contributors vs. track multiplicity for OFF
  TH2D *o = heventOFF->Projection(6,7);
  s1 = fix2DTitle(heventOFF->Projection(6)->GetTitle(), heventOFF->Projection(7)->GetTitle()); s1+=" (OFF)";
  o->SetTitle(s1);
  o->Draw("colz");
   
  if(heventHLT->GetNdimensions()==10){
     can2->cd(6);
     off = heventOFF->Projection(9); // V0 centrality, taken from the offline ESD
     off->SetTitle(fix1DTitle(heventOFF->Projection(9)->GetTitle()));
     off->SetLineColor(2);
     off->Draw();
  }  
  
  can1->SaveAs(folder+"/vertex_event_properties.root");
  can1->SaveAs(folder+"/vertex_event_properties.png");
  can2->SaveAs(folder+"/general_event_properties.root");
  can2->SaveAs(folder+"/general_event_properties.png");
  //delete can1;
  //delete can2;
    
  return;
}

void plotTrackQuantities( THnSparse* htrackHLT, THnSparse* htrackOFF, TText* hText, TString folder, cuts cut ){   
  
  htrackHLT->GetAxis(0)->SetRangeUser(cut.minPt,cut.maxPt);
  htrackHLT->GetAxis(1)->SetRangeUser(cut.minTPCclus,cut.maxTPCclus);
  htrackHLT->GetAxis(2)->SetRangeUser(cut.minEta, cut.maxEta);
  htrackHLT->GetAxis(4)->SetRangeUser(cut.minDCAr, cut.maxDCAr);
  htrackHLT->GetAxis(5)->SetRangeUser(cut.minDCAz, cut.maxDCAz);
  htrackHLT->GetAxis(7)->SetRangeUser(cut.minITSclus, cut.maxITSclus);
  if(cut.vertexStatus!=2) htrackHLT->GetAxis(8)->SetRangeUser(cut.vertexStatus, cut.vertexStatus);
  htrackHLT->GetAxis(9)->SetRangeUser(-TMath::Abs(cut.vertexZ), TMath::Abs(cut.vertexZ));
  if(htrackHLT->GetNdimensions()==11) htrackHLT->GetAxis(10)->SetRangeUser(cut.minV0cent, cut.maxV0cent);
  
  htrackOFF->GetAxis(0)->SetRangeUser(cut.minPt,cut.maxPt);
  htrackOFF->GetAxis(1)->SetRangeUser(cut.minTPCclus,cut.maxTPCclus);
  htrackOFF->GetAxis(2)->SetRangeUser(cut.minEta, cut.maxEta);
  htrackOFF->GetAxis(4)->SetRangeUser(cut.minDCAr, cut.maxDCAr);
  htrackOFF->GetAxis(5)->SetRangeUser(cut.minDCAz, cut.maxDCAz);
  htrackOFF->GetAxis(7)->SetRangeUser(cut.minITSclus, cut.maxITSclus);
  if(cut.vertexStatus!=2) htrackOFF->GetAxis(8)->SetRangeUser(cut.vertexStatus,cut.vertexStatus);
  htrackOFF->GetAxis(9)->SetRangeUser(-TMath::Abs(cut.vertexZ), TMath::Abs(cut.vertexZ));
  if(htrackOFF->GetNdimensions()==11) htrackOFF->GetAxis(10)->SetRangeUser(cut.minV0cent, cut.maxV0cent);
  
  TString tmp = "";
  tmp += "track properties for ";
  tmp+=hText->GetTitle();     
  TCanvas *can3 = new TCanvas("can3",tmp,1600,1000); 
  can3->Divide(4,2); 
  // the first 9 track related variables filled in the THnSparse
  //  0	    1     2    3     4      5      6     7   
  // pt  TPCcl  eta   phi   DCAr  DCAz charge  ITScl 
  
  TH1D *hlt = NULL; 
  TH1D *off = NULL;

  TLegend *leg = new TLegend(0.25,0.2,0.85,0.85);

  for(int i=0; i<8; i++){  
    hlt = htrackHLT->Projection(i); if(!hlt){ printf("plotTrackQuantities: empty HLT histogram for projection %d\n",i); continue; }
    off = htrackOFF->Projection(i); if(!off){ printf("plotTrackQuantities: empty OFF histogram for projection %d\n",i); continue; }     
    hlt->SetTitle(fix1DTitle(htrackHLT->Projection(i)->GetTitle())); 
    off->SetTitle(fix1DTitle(htrackOFF->Projection(i)->GetTitle())); // is necessary in cases where only offline data is available
  
    TString s = hlt->GetTitle();      
    if(s.Contains("p_")){ 
      s+=" (GeV/c)";
      hlt->SetXTitle(s);     
    }
    else if(s.Contains("phi")){
      s+=" (rad)"; 
      hlt->SetXTitle(s);
    }
    else if(s.Contains("DCA")){
      s+=" (cm)";
      hlt->SetXTitle(s);
    }
       
    if(off->GetEntries()>0) defineYaxisMax(hlt, off);
    off->SetLineColor(2);
   
    can3->cd(i+1);
    if(hlt->GetEntries()>0) hlt->Draw();
    if(off->GetEntries()>0) off->Draw("sames");
    if(hlt->GetEntries()>0 && off->GetEntries()>0) printStats(hlt, off);
    if(off->GetEntries()>0 && i==0 ) printLegend(hlt,off);
     
    if(hlt->GetEntries()>0 && i==0){
      leg->SetFillColor(kWhite);
      leg->SetLineColor(kWhite);
      leg->SetShadowColor(kWhite);
      s=""; s+=cut.minEta; s+="<#eta< "; s+=cut.maxEta;leg->AddEntry((TObject*)0, s, "");  
      s=""; s+=cut.minPt; s.Resize(4); s+="<p_{T} (GeV/c)<"; s+=cut.maxPt;  leg->AddEntry((TObject*)0, s, ""); 
      s=""; s+=cut.minDCAr; s+="<DCAr (cm)<"; s+=cut.maxDCAr; leg->AddEntry((TObject*)0, s, "");  
      s=""; s+=cut.minDCAz; s+="<DCAz (cm)<"; s+=cut.maxDCAz; leg->AddEntry((TObject*)0, s, "");  
      if(cut.minTPCclus!=0 && cut.maxTPCclus!=200){ s=""; s+=cut.minTPCclus; s+="<TPC cls/tr<"; s+=cut.maxTPCclus; leg->AddEntry((TObject*)0, s, "");}
      if(cut.minITSclus!=0 && cut.maxITSclus!=10){ s=""; s+=cut.minITSclus; s+="<ITS cls/tr<"; s+=cut.maxITSclus; leg->AddEntry((TObject*)0, s, "");}
      s=""; s+="|vertexZ| (cm)<"; s+=TMath::Abs(cut.vertexZ); leg->AddEntry((TObject*)0, s, ""); 
      if(cut.vertexStatus!=2) { s=""; s+="vertex status "; s+=cut.vertexStatus; leg->AddEntry((TObject*)0, s, ""); }
      if(htrackHLT->GetNdimensions()==11) { s=""; s+=cut.minV0cent; s+=" < V0 centr < "; s+=cut.maxV0cent; leg->AddEntry((TObject*)0, s, "");  }
      
      leg->Draw();
      
      can3->Update();
	}      
  } 
  TString strcuts = cutsToString(cut);
  
  can3->SaveAs(folder+"/track_properties_"+strcuts+".root");
  can3->SaveAs(folder+"/track_properties_"+strcuts+".png");
  delete can3;
  delete leg;

  return;
}

//====================== for 2D track distributions ===============================//

void plot2D( THnSparse* h, TText *hText, TString folder, cuts cut ){

  h->GetAxis(0)->SetRangeUser(cut.minPt,cut.maxPt);
  h->GetAxis(1)->SetRangeUser(cut.minTPCclus,cut.maxTPCclus);
  h->GetAxis(2)->SetRangeUser(cut.minEta, cut.maxEta);
  h->GetAxis(4)->SetRangeUser(cut.minDCAr, cut.maxDCAr);
  h->GetAxis(5)->SetRangeUser(cut.minDCAz, cut.maxDCAz);
  h->GetAxis(7)->SetRangeUser(cut.minITSclus,cut. maxITSclus);
  if(cut.vertexStatus!=2) h->GetAxis(8)->SetRangeUser(cut.vertexStatus,cut.vertexStatus);
  h->GetAxis(9)->SetRangeUser(-TMath::Abs(cut.vertexZ), TMath::Abs(cut.vertexZ));
  if(h->GetNdimensions()==11) h->GetAxis(10)->SetRangeUser(cut.minV0cent, cut.maxV0cent);
  
  TString name = h->GetName();
  TString tmp = "";
  if(name.Contains("HLT")) tmp = "HLT 2-D track distributions for ";
  else tmp = "OFF 2-D track distributions for ";

  tmp += hText->GetTitle();
  TCanvas *can4 = new TCanvas("can4",tmp,1200,800);
  can4->Divide(4,2);

  can4->cd(1);    
  TH2D *ht = h->Projection(1,0); // TPC clusters/track vs. pt
  ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(0)->GetTitle()));

  TString s = "";
  s = fix1DTitle(h->Projection(0)->GetTitle())+" (GeV/c)";
  ht->SetXTitle(s);
  ht->Draw("colz");
  
  can4->cd(2);
  ht = h->Projection(1,2); // TPC clusters/track vs. eta
  ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(2)->GetTitle()));
  ht->Draw("colz");
  
  can4->cd(3);
  ht = h->Projection(1,4); // TPC clusters/track vs. DCAr
  ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(4)->GetTitle()));
  s = fix1DTitle(h->Projection(4)->GetTitle())+" (cm)";
  ht->SetXTitle(s);
  ht->Draw("colz");
  
  can4->cd(4);
  ht = h->Projection(1,5); // TPC clusters/track vs. DCAz
  ht->SetTitle(fix2DTitle(h->Projection(1)->GetTitle(), h->Projection(5)->GetTitle()));
  s = fix1DTitle(h->Projection(5)->GetTitle())+" (cm)";
  ht->SetXTitle(s);
  ht->Draw("colz");
  
  can4->cd(5);
  ht = h->Projection(4,0); // DCAr vs. pt
  ht->SetTitle(fix2DTitle(h->Projection(4)->GetTitle(), h->Projection(0)->GetTitle()));
  s = fix1DTitle(h->Projection(0)->GetTitle())+" (GeV/c)";
  ht->SetXTitle(s);
  s = fix1DTitle(h->Projection(4)->GetTitle())+" (cm)";
  ht->SetYTitle(s);
  ht->Draw("colz");
  
  can4->cd(6);
  ht = h->Projection(5,3); // DCAz vs. pt
  ht->SetTitle(fix2DTitle(h->Projection(5)->GetTitle(), h->Projection(3)->GetTitle()));
  s = fix1DTitle(h->Projection(5)->GetTitle())+" (cm)";
  ht->SetYTitle(s);
  ht->Draw("colz");
  
  can4->cd(7);
  ht = h->Projection(2,0); // eta vs. pt
  ht->SetTitle(fix2DTitle(h->Projection(2)->GetTitle(), h->Projection(0)->GetTitle()));
  s = fix1DTitle(h->Projection(0)->GetTitle())+" (GeV/c)";
  ht->SetXTitle(s);
  ht->Draw("colz");
  
  can4->cd(8);
  ht = h->Projection(2,3); // eta vs. phi
  ht->SetTitle(fix2DTitle(h->Projection(2)->GetTitle(), h->Projection(3)->GetTitle()));
  s = fix1DTitle(h->Projection(3)->GetTitle())+" (rad)";
  ht->SetXTitle(s);
  ht->Draw("colz");
 
  TString strcuts = cutsToString(cut);
  if(name.Contains("HLT")){
     can4->SaveAs(folder+"/HLT_2D_track_correlations_"+strcuts+".root"); 
     can4->SaveAs(folder+"/HLT_2D_track_correlations_"+strcuts+".png"); 
  } else {
     can4->SaveAs(folder+"/OFF_2D_track_correlations_"+strcuts+".root"); 
     can4->SaveAs(folder+"/OFF_2D_track_correlations_"+strcuts+".png"); 
  }
  //delete can4;
  return;
}

TString cutsToString( cuts cut ){
 
  TString strcuts = "";
  char s[300]; sprintf(s, "eta%2g_%2g_Pt%2g_%2g_DCAr%2g_%2g_DCAz%2g_%2g_TPCclus%d_%d_ITSclus%d_%d_Zvertex%2g_cent%d_%d", 
                           cut.minEta,cut.maxEta,cut.minPt,cut.maxPt,cut.minDCAr,cut.maxDCAr,cut.minDCAz,cut.maxDCAz,cut.minTPCclus,cut.maxTPCclus,cut.minITSclus,
			   cut.maxITSclus,cut.vertexZ,cut.minV0cent,cut.maxV0cent);
  strcuts = s; strcuts.ReplaceAll(" ","");
 
  if(cut.vertexStatus!=2){
    char v[10]; 
    sprintf(v, "_VS%d",cut.vertexStatus);
    strcuts+=v;
  }
  return strcuts;
}

void printStats(TH1D *hlt, TH1D *off){  
  gPad->Update();
  TPaveStats *st1 = (TPaveStats*)hlt->FindObject("stats");
  st1->SetLineColor(0);
  //st1->SetTextSize(7);
  //st1->SetTextFont(8);

  gPad->Update();
  TPaveStats *st2 = (TPaveStats*)off->FindObject("stats");
  st2->SetY2NDC(st1->GetY1NDC()-0.05);
  st2->SetY1NDC(st2->GetY2NDC()-TMath::Abs(st1->GetY1NDC()-st1->GetY2NDC()));
  st2->SetLineColor(0);
  st2->SetTextColor(off->GetLineColor());
  st2->SetFillStyle(0);
  //st2->SetTextSize(7);
  //st2->SetTextFont(8);
  st2->Draw();
  return;
}

void defineYaxisMax(TH1D *h1, TH1D *h2){ 
  //Y axis
  if(h1->GetMaximum() > h2->GetMaximum()) h2->SetMaximum(1.1*h1->GetMaximum());
  else h1->SetMaximum(1.1*h2->GetMaximum());
  
  h1->SetMinimum(0);
  h2->SetMinimum(0);
 
  // X axis  
  double xmin, xmax;  
  if(h1->GetBinLowEdge(1) > h2->GetBinLowEdge(1)) xmin = h1->GetBinLowEdge(1);
  else xmin = h2->GetBinLowEdge(1);
  if(h1->GetBinLowEdge(h1->GetNbinsX()+1) > h2->GetBinLowEdge(h1->GetNbinsX()+1)) xmax = h1->GetBinLowEdge(h1->GetNbinsX()+1);
  else xmax = h2->GetBinLowEdge(h2->GetNbinsX()+1);
  
  h2->SetAxisRange(xmin, xmax, "X");  
  return;
}

void printLegend(TH1D *hlt, TH1D *off){  
  TLegend *l = new TLegend(0.68,0.16,0.88,0.36);
  l->SetFillColor(10); 
  l->SetLineColor(10);
  l->AddEntry(hlt, "HLT", "l");
  l->AddEntry(off, "OFF", "l");
  l->Draw("same");
  return;
}

TString fix1DTitle(const char* c){
  TString tmp = c;
  tmp.ReplaceAll("projection ","");
  return tmp;   
}

TString fix2DTitle(const char* c1, const char* c2){
  TString tmp = fix1DTitle(c1)+" vs."+fix1DTitle(c2);
  return tmp;
}

void printCuts(cuts cut){
  printf("\n %2g<eta<%2g, %2g<pt (GeV/c)<%2g, %2g<DCAr (cm)<%2g, %2g<DCAz (cm)<%2g, %d<TPCclus<%d, %d<ITSclus<%d, vertex status %d, |vertexZ| (cm)<%2g, %d<centr (%)<%d \n\n",cut.minEta, cut.maxEta, cut.minPt, cut.maxPt, cut.minDCAr, cut.maxDCAr, cut.minDCAz, cut.maxDCAz, cut.minTPCclus, cut.maxTPCclus, cut.minITSclus, cut.maxITSclus, cut.vertexStatus, cut.vertexZ, cut.minV0cent, cut.maxV0cent );
}
